package com.ophiux.cs.infrastructure.compoment.basedata.mybatis;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.hibernate.dialect.Dialect;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ophiux.cs.infrastructure.compoment.basedata.mybatis.handler.DataHandler;
import com.ophiux.cs.infrastructure.compoment.basedata.mybatis.handler.DataHandlerImpl;
import com.ophiux.cs.infrastructure.compoment.basedata.mybatis.interceptor.MysqlOffsetLimitInterceptor;

@Service
public class MysqlDataComponentImpl implements DataComponent {
	@Autowired
	private SqlSessionTemplate dataService;
	private String idName;
	private String batchIDName;
	private Dialect dialect;
	private SqlSessionFactory sqlSessionFactory;

	public MysqlDataComponentImpl() {
		this.idName = "id";
		this.batchIDName = "batchID";
	}

	public void initialize() {
		if (this.dialect != null) {
			MysqlOffsetLimitInterceptor offsetLimitInterceptor = new MysqlOffsetLimitInterceptor();
			offsetLimitInterceptor.setDialect(this.dialect);
			this.sqlSessionFactory.getConfiguration().addInterceptor(offsetLimitInterceptor);
		}

		this.dataService = new SqlSessionTemplate(this.sqlSessionFactory);
	}

	public int insertData(String insertData, Object parameter) {

		return this.dataService.insert(insertData, parameter);
	}

	public int updateData(String statement, Object parameter) {

		return this.dataService.update(statement, parameter);

	}

	public int deleteData(String statement, Object parameter) {

		return this.dataService.delete(statement, parameter);
	}

	public Map getDataByID(String paramString, Object paramObject) {

		return (Map) this.dataService.selectOne(paramString, paramObject);
	}

	public Object getObject(String paramString, Object paramObject) {
		return this.dataService.selectOne(paramString, paramObject);
	}

	public List getData(String statement, Object parameter) {
		return this.dataService.selectList(statement, parameter);
	}

	public EnterprisePage getDataPageBatch(String getData, String getDataCount, Object parameter,
			EnterprisePage enterprisePage) {
		return executeDataPageBatch(getData, getDataCount, parameter, enterprisePage);
	}

	public DataHandler createDataHandler(Object parameter) {
		if (parameter == null) {
			return new DataHandlerImpl(new HashMap());
		}
		return new DataHandlerImpl(createParameter(parameter));
	}

	public void executeBatch(DataHandler paramDataHandler) {
		executeDataBatch(paramDataHandler);
	}

	public void deleteDataBatch(String paramString, Object paramObject) {
		executeDataBatch(paramString, createParameter(paramObject));
	}

	private void executeDataBatch(String batchName, Map parameter) {
		List list = new ArrayList();
		list.add(parameter);
		executeDataBatch(batchName, list);
	}

	private void executeDataBatch(String batchName, List parameter) {
		String[] batchNames = null;
		if ((batchName != null) && (!"".equals(batchName))) {
			batchNames = batchName.split(",");
		}
		if (batchNames != null) {
			int lr = 0;
			for (int count = parameter.size(); lr < count; lr += 1) {
				int l = 0;
				for (int batchCount = batchNames.length; l < batchCount; l += 1) {
					String result = batchNames[l];
					if (result.indexOf(".insert") > 0) {
						Map map = (Map) parameter.get(lr);
						this.dataService.insert(result, map);
					} else if (batchName.indexOf(".update") > 0) {
						this.dataService.update(result, parameter.get(lr));
					} else if ((result.indexOf(".delete") > 0) || (result.indexOf(".batchDelete") > 0)) {
						this.dataService.delete(result, parameter.get(lr));
					} else {
						this.dataService.insert(result, parameter.get(lr));
					}
				}
			}
		}
	}

	private void executeDataBatch(DataHandler dataHandler) {
		for (Map handler : dataHandler.getHandler())
			if (handler != null)
				if (handler.containsKey("handlerName")) {
					String handlerName = (String) handler.get("handlerName");
					if ("insertData".equals(handlerName)) {
						Object parameter = handler.get("parameter");
						Iterator iterator;
						if ((parameter != null) && ((parameter instanceof List))) {
							for (iterator = ((List) parameter).iterator(); iterator.hasNext();) {
								Object result = iterator.next();
								this.dataService.insert((String) handler.get("handleDataName"), result);
							}
						} else {
							this.dataService.insert((String) handler.get("handleDataName"), handler.get("parameter"));
						}

					} else if ("updateData".equals(handlerName)) {
						this.dataService.update((String) handler.get("handleDataName"), handler.get("parameter"));
					} else if ("deleteData".equals(handlerName)) {
						this.dataService.delete((String) handler.get("handleDataName"), handler.get("parameter"));
					} else if ("getData".equals(handlerName)) {
						dataHandler.setDataView((String) handler.get("name"), this.dataService
								.selectList((String) handler.get("handleDataName"), handler.get("parameter")));
					} else if ("getObject".equals(handlerName)) {
						dataHandler.setDataView((String) handler.get("name"), this.dataService
								.selectOne((String) handler.get("handleDataName"), handler.get("parameter")));
					} else if ("getDataPage".equals(handlerName)) {
						dataHandler.setDataView((String) handler.get("name"),
								executeDataPageBatch((String) handler.get("getData"),
										(String) handler.get("getDataCount"), handler.get("parameter"),
										(EnterprisePage) handler.get("enterprisePage")));
					}

				} else {
					System.err.println("[ERROR]can not find SQLStatement");
				}
	}

	/**
	 * 
	 * Description:分页辅助工具类 <br>
	 * 
	 * @param getData
	 * @param getDataCount
	 * @param parameter
	 * @param enterprisePage
	 * @return
	 */
	private EnterprisePage executeDataPageBatch(String getData, String getDataCount, Object parameter,
			EnterprisePage enterprisePage) {
		if (enterprisePage.getPageRows() > 0) {
			if ((getDataCount != null) && (!"".equals(getDataCount))) {
				enterprisePage.setRowSum(((Integer) this.dataService.selectOne(getDataCount, parameter)).intValue());
			}

			int pageCurrent = enterprisePage.getPageCurrent();
			if (pageCurrent > 0) {
				pageCurrent -= 1;
			}
			enterprisePage.setRowDatas(this.dataService.selectList(getData, parameter,
					new RowBounds(enterprisePage.getPageRows(), pageCurrent * enterprisePage.getPageRows())));
		} else {
			enterprisePage.setRowDatas(this.dataService.selectList(getData, parameter));

			enterprisePage.setRowSum(enterprisePage.getRowDatas().size());
		}
		return enterprisePage;
	}

	@SuppressWarnings("rawtypes")
	private Map createParameter(Object parameter) {
		if ((parameter instanceof Map))
			return (Map) parameter;
		try {
			return PropertyUtils.describe(parameter);
		} catch (Exception exception) {
			exception.printStackTrace();
		}
		return new HashMap();
	}

	public Dialect getDialect() {
		return dialect;
	}

	public void setDialect(Dialect dialect) {
		this.dialect = dialect;
	}

	public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}

}